package net.hands.common.coll;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import net.hands.common.Convert;
import net.hands.common.JsonUtils;

/**
 * 说明:抽象键值对map扩展
 * <br>
 * <p>这是一个开源的软件，请在LGPLv3下合法使用、修改或重新发布。</p>
 * @author 陈侃(cknet@126.com, 13910090885)
 *         http://code.google.com/p/simpleframework/
 *         http://www.simpleframework.net
 */
@SuppressWarnings({ "serial", "unchecked" })
public abstract class AbstractKVMap<T, M extends AbstractKVMap<T, M>> implements Map<String, T>,
		Serializable {
	/**
	 * 键值map
	 */
	private Map<String, T> kv;
	
	/* 设置插入的null值 */
	private T nullVal;
   /**
    * 
   * Constructor Method  
   * @update 2012-9-20 上午11:01:35  
   * @param initialCapacity  初始容量
    */
	public AbstractKVMap(final int initialCapacity) {
		kv = create(initialCapacity);
	}
   /**
    * 
   * Constructor Method  
   * @update 2012-9-20 上午11:01:44
    */
	public AbstractKVMap() {
		this(16);//初始容量为16个
	}
   /**
    * 说明:创建容器
   * @param initialCapacity 初始容量
   * @return Map<String, T>
   * @update 2012-9-20 上午11:04:03
    */
	protected Map<String, T> create(final int initialCapacity) {
		return new LinkedHashMap<String, T>(initialCapacity);
	}
   /**
   * 说明:添加键值对
   * @param key 键
   * @param value 值
   * @return   AbstractKVMap<T, M>
   * @update 2012-9-20 上午11:09:30
    */
	public M add(final String key, final T value) {
		put(key, value);
		return (M) this;
	}
   /**
   * 说明:添加map
   * @param m  容器
   * @return AbstractKVMap<T, M>
   * @update 2012-9-20 上午11:12:48
    */
	public M addAll(final Map<String, T> m) {
		putAll(m);
		return (M) this;
	}
   /**
   * 说明:添加 (缺省实现)
   * @param index 索引
   * @param key  键
   * @param value 值
   * @return AbstractKVMap<T, M>
   * @update 2012-9-20 上午11:13:36
    */
	public M add(final int index, final String key, final T value) {
		return (M) this;
	}
   /**
   * 说明:获得map
   * @return Map<String, T>
   * @update 2012-9-20 上午11:14:21
    */
	public Map<String, T> map() {
		return kv;
	}
   /**
   * 说明:map转json 
   * @return String
   * @update 2012-9-20 上午11:14:40
    */
	public String toJSON() {
		return JsonUtils.toJSON(kv);
	}

	// for caseInsensitive
   /**
    * 忽略大小写键的容器 <小写键 : 原始键>
    */
	private Map<String, String> caseInsensitiveKeys;
   /**
    * 是否忽略大小写
    */
	private boolean caseInsensitive;
  /**
  * 说明:获得是否忽略大小写
  * @return boolean
  * @update 2012-9-20 上午11:15:58
   */
	public boolean isCaseInsensitive() {
		return caseInsensitive;
	}
   /**
   * 说明:设置是否忽略大小写
   * @param caseInsensitive 忽略大小写
   * @return AbstractKVMap<T, M>
   * @update 2012-9-20 上午11:16:09
    */
	public M setCaseInsensitive(final boolean caseInsensitive) {
		if (caseInsensitive) {//如果忽略大小写,创建忽略大小写键的容器 
			caseInsensitiveKeys = new HashMap<String, String>();
		}
		this.caseInsensitive = caseInsensitive;
		return (M) this;
	}
   /**
    * 
   * 说明：获得空键
   * @return T
   * @update 2012-10-31 上午10:30:18
    */
	public T getNullVal() {
		return nullVal;
	}
   /**
    * 
   * 说明：设置空键
   * @param nullVal
   * @return M
   * @update 2012-10-31 上午10:31:24
    */
	public M setNullVal(final T nullVal) {
		this.nullVal = nullVal;
		return (M) this;
	}
   /**
   * 说明:键变为小写
   * @param key 键
   * @return String
   * @update 2012-9-20 上午11:16:35
    */
	protected String caseInsensitiveKey(final String key) {
		return key.toLowerCase();
	}
  /**
  * 说明: 键字符,如果是忽略大小写 根据小写键 从容器中获得原键
  * @param key 键对象
  * @return String
  * @update 2012-9-20 上午11:17:54
   */
	protected String key(final Object key) {
		final String key2 = Convert.toString(key);
		return caseInsensitiveKeys != null ? caseInsensitiveKeys.get(caseInsensitiveKey(key2)) : key2;
	}

	// map implement
  /**
   * 忽略带下写容器不为null , 忽略带下写容器 存入 小写键:原键  ,键值 容器存放 原键 值
  (non-Javadoc)  
  * @see java.util.Map#put(java.lang.Object, java.lang.Object)  
  * @update 2012-9-20 上午11:18:25
   */
	@Override
	public T put(final String key, final T value) {
		if (caseInsensitiveKeys != null) {//如果忽略带下写容器不为null 
			caseInsensitiveKeys.put(caseInsensitiveKey(key), key); //存入 小写键:原键
		}
		return kv.put(key, value != null ? value : getNullVal());//键值 容器存放 原键 值
	}
   /**
    * 内部调用key(final Object key) 
   (non-Javadoc)  
   * @see java.util.Map#get(java.lang.Object)  
   * @update 2012-9-20 上午11:18:40
    */
	@Override
	public T get(final Object key) {
		return kv.get(key(key));
	}
   /**
    * 
   (non-Javadoc)  
   * @see java.util.Map#remove(java.lang.Object)  
   * @update 2012-9-20 上午11:18:51
    */
	@Override
	public T remove(final Object key) {
		return kv.remove(key(key));
	}
   /**
    *内部调用put(final String key, final T value) 
   (non-Javadoc)  
   * @see java.util.Map#putAll(java.util.Map)  
   * @update 2012-9-20 上午11:18:59
    */
	@Override
	public void putAll(final Map<? extends String, ? extends T> m) {
		if (m == null) {
			return;
		}
		for (final Map.Entry<? extends String, ? extends T> e : m.entrySet()) {
			put(e.getKey(), e.getValue());
		}
	}
   /**
    * 清除忽略大小写键容器 清除简直容器
   (non-Javadoc)  
   * @see java.util.Map#clear()  
   * @update 2012-9-20 上午11:19:09
    */
	@Override
	public void clear() {
		if (caseInsensitiveKeys != null) {
			caseInsensitiveKeys.clear();//清楚忽略大小写键容器
		}
		kv.clear();//清楚简直容器
	}
   /**
    * 
   (non-Javadoc)  
   * @see java.util.Map#entrySet()  
   * @update 2012-9-20 上午11:19:17
    */
	@Override
	public Set<Map.Entry<String, T>> entrySet() {
		return kv.entrySet();
	}
   /**
    * 
   (non-Javadoc)  
   * @see java.util.Map#keySet()  
   * @update 2012-9-20 上午11:19:21
    */
	@Override
	public Set<String> keySet() {
		return kv.keySet();
	}
   /**
    * 
   (non-Javadoc)  
   * @see java.util.Map#values()  
   * @update 2012-9-20 上午11:19:27
    */
	@Override
	public Collection<T> values() {
		return kv.values();
	}
   /**
    * 
   (non-Javadoc)  
   * @see java.util.Map#size()  
   * @update 2012-9-20 上午11:19:33
    */
	@Override
	public int size() {
		return kv.size();
	}
   /**
    * 
   (non-Javadoc)  
   * @see java.util.Map#isEmpty()  
   * @update 2012-9-20 上午11:19:37
    */
	@Override
	public boolean isEmpty() {
		return kv.isEmpty();
	}
   /**
    * 
   (non-Javadoc)  
   * @see java.util.Map#containsKey(java.lang.Object)  
   * @update 2012-9-20 上午11:19:42
    */
	@Override
	public boolean containsKey(final Object key) {
		return kv.containsKey(key(key));
	}
   /**
    * 
   (non-Javadoc)  
   * @see java.util.Map#containsValue(java.lang.Object)  
   * @update 2012-9-20 上午11:19:47
    */
	@Override
	public boolean containsValue(final Object value) {
		return kv.containsValue(value);
	}
	/**
	 * 空的map
	 */
	@SuppressWarnings("rawtypes")
	public static Map NULL_MAP = Collections.EMPTY_MAP;
}
